package com.chenggcode.simple.log.filter;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.AbstractRequestLoggingFilter;

import java.util.Enumeration;
import java.util.Objects;

/**
 * @author Chenggcode
 * @date 2025/6/19 11:32
 */
@Slf4j
public class MyRequestLoggingFilter extends AbstractRequestLoggingFilter {
    private static final ThreadLocal<Long> START_TIME = ThreadLocal.withInitial(() -> 0L);
    private String beforeMessagePrefix = DEFAULT_BEFORE_MESSAGE_PREFIX;
    private String afterMessagePrefix = DEFAULT_AFTER_MESSAGE_PREFIX;

    @Override
    public void setBeforeMessagePrefix(String beforeMessagePrefix) {
        super.setBeforeMessagePrefix(beforeMessagePrefix);
        this.beforeMessagePrefix = beforeMessagePrefix;
    }

    @Override
    public void setAfterMessagePrefix(String afterMessagePrefix) {
        super.setAfterMessagePrefix(afterMessagePrefix);
        this.afterMessagePrefix = afterMessagePrefix;
    }

    @Override
    protected void beforeRequest(HttpServletRequest request, String message) {
        START_TIME.set(System.currentTimeMillis());
        log.info(message);
    }

    @Override
    protected void afterRequest(HttpServletRequest request, String message) {
        START_TIME.remove();
        log.info(message);
    }

    @Override
    public String createMessage(HttpServletRequest request, String prefix, String suffix) {
        StringBuilder msg = new StringBuilder();
        if (Objects.equals(prefix, this.beforeMessagePrefix)) {
            msg.append(request.getMethod()).append(" ");
            msg.append(request.getRequestURI());
            if (isIncludeQueryString()) {
                String queryString = request.getQueryString();
                if (queryString != null) {
                    msg.append('?').append(queryString);
                }
            }

            if (isIncludeClientInfo()) {
                String client = request.getRemoteAddr();
                if (StringUtils.hasLength(client)) {
                    msg.append(", client=").append(client);
                }
                HttpSession session = request.getSession(false);
                if (session != null) {
                    msg.append(", session=").append(session.getId());
                }
                String user = request.getRemoteUser();
                if (user != null) {
                    msg.append(", user=").append(user);
                }
            }

            if (isIncludeHeaders()) {
                HttpHeaders headers = new ServletServerHttpRequest(request).getHeaders();
                HttpHeaders loggedHeaders = new HttpHeaders();
                Enumeration<String> names = request.getHeaderNames();
                while (names.hasMoreElements()) {
                    String header = names.nextElement();
                    if (getHeaderPredicate().test(header)) {
                        loggedHeaders.put(header, headers.get(header));
                    }
                }
                msg.append(", headers=").append(loggedHeaders);
            }
        }


        if (Objects.equals(this.afterMessagePrefix, prefix)) {
            if (isIncludePayload()) {
                String payload = getMessagePayload(request);
                msg.append("payload=").append(payload);
            }
            msg.append(", costs=").append(System.currentTimeMillis() - START_TIME.get()).append("ms");
        }
        return msg.toString();
    }
}
